package com.example.reactive.config;

import com.example.reactive.vo.UserVO;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;

@Configuration
public class ReactiveConfig {

    // WebClient 是一种反应式客户端，可通过流畅的 API 执行 HTTP 请求。
    // WebClient 配置参考 Spring 官网 https://docs.springjava.cn/spring-framework/reference/web/webflux-webclient.html
    @Bean
    public WebClient webClient() {
        // 要自定义 Reactor Netty 设置，请提供一个预配置的 HttpClient：
        HttpClient httpClient = HttpClient.create();

        // 创建一个 WebClient 实例, 用于发送 HTTP 请求。许可定制化配置
        // 参考 https://docs.springjava.cn/spring-framework/reference/web/webflux-webclient/client-builder.html
        return WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .build();
    }


    public Mono<String> getGreeting(WebClient client) {
        // 适用于简单的 GET 请求
        Mono<UserVO> entityMono = client.get()
                .uri("/persons/1")
                .accept(MediaType.APPLICATION_JSON)
                // 适用于需要更多控制的高级情况，例如根据响应状态对响应进行不同的解码
                .exchangeToMono(response -> {
                    if (response.statusCode().equals(HttpStatus.OK)) {
                        return response.bodyToMono(UserVO.class);
                    }
                    else {
                        // Turn to error
                        return response.createError();
                    }
                });
        return entityMono.thenReturn("success");
    }


    public Mono<String> postGreeting(WebClient client) {
        Mono<UserVO> personMono = Mono.just(new UserVO("John", "Doe"));
        // 适用于简单的 POST 请求
        Mono<Void> result = client.post()
                .uri("/persons/{id}", 123)
                .contentType(MediaType.APPLICATION_JSON)
                .body(personMono, UserVO.class)
                // retrieve() 方法可用于声明如何提取响应
                .retrieve()
                .bodyToMono(Void.class);
        return result.thenReturn("success");
    }

}

// Spring WebFlux 包含一个用于执行 HTTP 请求的客户端。WebClient 具有基于 Reactor 的功能性流畅 API（请参阅 “Reactive Libraries”），
// 可以声明式地组成异步逻辑，而无需处理线程或并发问题。它是完全无阻塞的，支持流式传输，并依赖于同样的编解码器，这些编解码器也用于对服务器端的请求和响应内容进行编码和解码。

// WebClient 配置参考 Spring 官网 https://docs.springjava.cn/spring-framework/reference/web/webflux-webclient.html